package onvifprotocol

import (
	"context"
	"errors"
	"fmt"
	"github.com/use-go/onvif"
	"go.uber.org/zap"
	"iot-base/common/logger"
	"net/http"
	"time"
)

type CameraDevice struct {
	device *onvif.Device
}

func NewCameraDevice(xaddr string, username string, pwd string) (*CameraDevice, error) {
	dev, err := onvif.NewDevice(xaddr)
	if err != nil {
		logger.Log.Error("NewMedia err:", zap.Error(err))
		return nil, err
	}
	dev.Authenticate(username, pwd)
	return &CameraDevice{
		dev,
	}, nil
}

func (m *CameraDevice) CallMethod(method interface{}) ([]byte, error) {
	var resp []byte
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
	defer cancel()
	done := make(chan error, 1)
	go func() {
		defer func() {
			if r := recover(); r != nil {
				logger.Log.Error("CallMethod", zap.Error(r.(error)))
				done <- r.(error)
			}
		}()
		httpResp, err := m.device.CallMethod(method)
		if httpResp != nil {
			defer httpResp.Body.Close()
		}
		if err != nil {
			done <- err
		}
		resp, err = readResponse(httpResp)
		logger.Log.Info(fmt.Sprintf("CallMethod xml resp: %v", string(resp)))
		fmt.Println("返回:\n", string(resp))
		if httpResp.StatusCode != http.StatusOK {
			done <- errors.New("error return from http")
		}
		done <- err
	}()
	select {
	case err := <-done:
		return resp, err
	case <-ctx.Done():
		return resp, ctx.Err()
	}
}
